home *** CD-ROM | disk | FTP | other *** search
- Subject: retouch(1): force changed date
- Keywords: touch, sccs, ls
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 5, Issue 4
- Submitted by: seismo!s3sun!gould9!joel (Joel West @ CACI)
-
- retouch(1) is like touch(1), except it uses the sccs id instead
- of the current time.
-
- It also contains a nifty subroutine that can be used as the inverse of
- localtime(3) or gmtime(3), to convert a date to the UNIX time format.
- The algorithm is brute force, but deterministic, and involves no
- UNIX proprietary source code.
-
- Joel West (619) 457-9681
- CACI, Inc. Federal, 3344 N. Torrey Pines Ct., La Jolla, CA 92037
- {cbosgd, ihnp4, sdcsvax, ucla-cs} !gould9!joel
- joel%gould9.uucp@NOSC.ARPA
-
- #!/bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #!/bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # Makefile
- # retouch.c
- # This archive created: Tue May 13 21:52:48 1986
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'README'" '(1001 characters)'
- if test -f 'README'
- then
- echo shar: over-writing existing file "'README'"
- fi
- sed 's/^X//' << \SHAR_EOF > 'README'
- Xretouch is a command that can be used to "correct" last changed
- Xdates, such as when by 'make' or 'ls -l -t'. These dates
- Xcan be inaccurate after a cp, or uucp, or kermit to create a new
- Xcopy of an existing file, or to import it from another system.
- X
- Xretouch looks for an sccs string of the form
- X @(#) anything at all mm/dd/yy
- X @(#) anything at all yy/mm/dd
- Xto get the date. It is intended for use on source files, and
- Xassumes there is no such string if it's not in the top 10 lines.
- X
- XIt has the following options:
- X -v verbose
- X -g assume the date is GMT rather than local time
- X -d date set the last change date to "date".
- X
- XIt has defs for BSD and USG, although it's been tested only
- Xunder BSD. It was intended as a one-time hack, and may not
- Xbe as clean as it should be, but it has proven versatile and
- Xnecessary over the past 6 months.
- X
- XI'd appreciate any suggestions or changes.
- X
- X Joel West CACI, Inc. Federal, La Jolla
- X {cbosgd, ihnp4, sdcsvax, ucla-cs} !gould9!joel
- X joel%gould9.uucp@NOSC.ARPA
- SHAR_EOF
- if test 1001 -ne "`wc -c 'README'`"
- then
- echo shar: error transmitting "'README'" '(should have been 1001 characters)'
- fi
- echo shar: extracting "'Makefile'" '(50 characters)'
- if test -f 'Makefile'
- then
- echo shar: over-writing existing file "'Makefile'"
- fi
- sed 's/^X//' << \SHAR_EOF > 'Makefile'
- Xretouch: retouch.c
- X cc -DBSD -o retouch retouch.c
- SHAR_EOF
- if test 50 -ne "`wc -c 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 50 characters)'
- fi
- echo shar: extracting "'retouch.c'" '(6231 characters)'
- if test -f 'retouch.c'
- then
- echo shar: over-writing existing file "'retouch.c'"
- fi
- sed 's/^X//' << \SHAR_EOF > 'retouch.c'
- X/* @(#) retouch.c 1.0 10/25/85
- X*/
- X/* retouch.c: set update time to match SCCS id
- X
- X Copyright (c) 1985, Joel West (ihnp4!gould9!joel)
- X License for non-commercial use freely granted as long
- X as this notice is retained.
- X
- X The id should be of the form
- X @(#) xxxxxxx 10/23/85
- X or @(#) xxxxxxx 85/10/23
- X it assumes date is the last non-blank thing on the line
- X and this program will only work between 1970 and 2000, inclusive
- X
- X works best if only one id (ignores others) and if id is at the
- X top of the file.
- X
- X Does not retouch if not found in first 10 lines; should be
- X an optionable parameter. A line is a newline or a null,
- X so this just might work on a binary file.
- X
- X*/
- X
- X#include <sys/types.h>
- Xtypedef struct {
- X time_t actime;
- X time_t modtime;
- X} utimbuf;
- X
- X#include <sys/stat.h>
- X#include <errno.h>
- X#ifdef BSD
- Xextern int errno;
- X#endif
- X
- X#include <stdio.h>
- X#define ungetchar(c) ungetc(c,stdin)
- X
- X#ifdef BSD
- X# include <strings.h>
- X# include <sys/time.h>
- X#else
- X# include <string.h>
- X# include <time.h>
- X#endif
- X#ifdef USG
- X# define index(s,c) strchr(s,c)
- X#endif
- X
- X#ifndef TRUE
- X# define TRUE (1)
- X# define FALSE (0)
- X#endif
- X
- X/* below are hour and minute at local time that should be
- X time-stamped; default 00:00:00. No user control over seconds */
- X#define STDHR 00
- X#define STDMIN 00
- X
- X#define SCCSKEY "@(#)"
- X#define SCCSCHR '@'
- X
- X#define EOL '\n'
- X#define EOS '\0'
- X
- Xint optg = 0, optd = 0, optv = 0;
- Xlong stddate;
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar **argv;
- X{ int depthlim,line,i,sccslen,touched;
- X char *p,*filenam,buff[1024];
- X int c,errind;
- X
- X depthlim = 10;
- X sccslen = strlen(SCCSKEY);
- X errind = 0;
- X
- X for (i = 1; i<argc && errind == 0; i++)
- X { if (*argv[i] != '-')
- X break;
- X p = argv[i];
- X while (*(++p))
- X switch(*p)
- X { case 'g':
- X optg++;
- X break;
- X case 'v':
- X optv++;
- X break;
- X case 'd':
- X if (optd)
- X errind++;
- X else
- X { optd++;
- X stddate = dateatol(argv[++i]);
- X if (stddate < 0)
- X { fprintf(stderr,"%s: invalid date format\n",argv[i]);
- X exit (0);
- X }
- X }
- X break;
- X default:
- X errind++;
- X }
- X }
- X
- X if (errind || i >= argc)
- X { fprintf(stderr,
- X "usage: %s [-v ] [-g] [-d date] file1 [file2 ... ]\n",
- X argv[0]);
- X exit (0);
- X }
- X
- X for (; i<argc; i++)
- X { filenam = argv[i];
- X if (freopen(filenam, "r", stdin) == NULL)
- X { perror(filenam);
- X exit(errno);
- X }
- X touched = 0;
- X if (optd) /* one date for all */
- X { setupdtime(filenam, stddate);
- X touched++;
- X goto settouch;
- X }
- X
- X for (line = 1; line <= depthlim; line++)
- X { while ( 1 )
- X { c = getchar();
- X if (c == EOF)
- X goto settouch;
- X if (c == EOS || c == EOL)
- X break;
- X if (c == SCCSCHR)
- X {
- X ungetchar(c);
- X gets(buff); /* won't work on binary */
- X if (strncmp(buff, SCCSKEY, sccslen) == 0)
- X { p = buff+strlen(buff); /* use last nonblank */
- X while (*(--p) == ' ') /* field in string */
- X ;
- X while (*p != ' ' && *p != '\t')
- X --p;
- X if ( setupdtime(filenam, dateatol(++p)) )
- X touched++;
- X goto settouch;
- X }
- X }
- X } /* within line */
- X } /* end of line */
- Xsettouch:
- X if (touched==0)
- X fprintf(stderr, "%s: not retouched\n", filenam);
- X else
- X if (optv)
- X fprintf(stderr, "%s: retouched\n", filenam);
- X } /* end of file */
- X}
- X
- X/* Reset the file's update time to the specified date. If the date is dubious,
- X don't reset it at all
- X*/
- Xint setupdtime(fname, mtime)
- Xchar *fname;
- Xlong mtime;
- X{ utimbuf timep;
- X struct stat statbuf;
- X
- X stat(fname, &statbuf);
- X timep.actime = statbuf.st_atime; /* copy current accessed time */
- X
- X if (mtime > 0) /* valid date */
- X { timep.modtime = mtime;
- X utime(fname, &timep);
- X return (TRUE);
- X }
- X return (FALSE);
- X}
- X
- X#define NSECYR 31536000
- X/* 365*24*60*60 */
- X#define NSECDA 86400
- X#define APPROXT(yr,mo,da) (((yr-70)*NSECYR) + ((mo*30)+da)*NSECDA)
- X#define INVDATE (-1)
- Xlong dateatol(string)
- Xchar *string;
- X{ char *p,*q;
- X int mdy[3],mo,da,yr,i,num;
- X struct tm *tmptr;
- X long timsec,approxsec,deltasec,lasttimsec,maxdelta,mindelta;
- X int deltasign;
- X static char *numstr = "0123456789";
- X
- X p = string;
- X while (*p == ' ') /* skip leading blanks */
- X p++;
- X for (i = 0 ; i<3; i++)
- X { num = 0;
- X q = NULL; /* watch for null field */
- X while (*p != EOS && *p != '/' && *p != ' ')
- X { q = index(numstr,*p++);
- X if (q == NULL) /* invalid digit */
- X break;
- X num = num*10 +(q-numstr);
- X }
- X if (q)
- X mdy[i] = num;
- X else
- X return (INVDATE); /* invalid or null field */
- X p++; /* skip delimiter */
- X }
- X --p;
- X while (*p++ == ' ')
- X ;
- X if (*--p != EOS) /* not end of string */
- X return (INVDATE);
- X
- X if (mdy[0] > 11)
- X { yr = mdy[0]; /* assume YY/MM/DD */
- X mo = mdy[1] - 1; /* months 0..11 not 1..12 */
- X da = mdy[2];
- X }
- X else
- X { mo = mdy[0] - 1; /* assume MM/DD/YY */
- X da = mdy[1];
- X yr = mdy[2];
- X }
- X
- X if (yr > 1900)
- X yr = yr - 1900;
- X
- X approxsec = APPROXT(yr,mo,da);
- X timsec = approxsec;
- X lasttimsec = 0;
- X mindelta = NSECDA;
- X maxdelta = NSECYR;
- X while (1)
- X { tmptr = (optg ? gmtime(&timsec) : localtime(&timsec)) ;
- X/* decode absolute time into local or gmt */
- X if (yr == tmptr->tm_year &&
- X mo == tmptr->tm_mon &&
- X da == tmptr->tm_mday)
- X {
- X/* the date is right, set the time to midnight local time; this
- Xmay behave strangely on daylight savings time changeover days */
- X if (STDHR == tmptr->tm_hour &&
- X STDMIN == tmptr->tm_min &&
- X 0 == tmptr->tm_sec)
- X break; /* exactly right */
- X else
- X { timsec -= (tmptr->tm_hour - STDHR) * 3600 +
- X (tmptr->tm_min - STDMIN) * 60 +
- X tmptr->tm_sec;
- X maxdelta = mindelta;
- X mindelta = 1;
- X }
- X }
- X else
- X { deltasec = APPROXT(tmptr->tm_year,tmptr->tm_mon,tmptr->tm_mday)
- X - approxsec;
- X deltasign = (deltasec < 0) ? -1 : 1;
- X/* approximately the difference in the number of seconds between
- X the guessed date and the actual date */
- X if (abs(deltasec) > abs(timsec-lasttimsec))
- X deltasec = timsec-lasttimsec;
- X deltasec = abs(deltasec);
- X deltasec = (deltasec > maxdelta) ? deltasec / 2 :
- X ((deltasec >= mindelta) ? (deltasec-1) : mindelta);
- X lasttimsec = timsec;
- X timsec -= deltasec * deltasign; /* binary convergence */
- X }
- X }
- X
- X return (timsec);
- X}
- SHAR_EOF
- if test 6231 -ne "`wc -c 'retouch.c'`"
- then
- echo shar: error transmitting "'retouch.c'" '(should have been 6231 characters)'
- fi
- # End of shell archive
- exit 0
-
-